package com.example.smartagrisys.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.smartagrisys.common.ResultCode;
import com.example.smartagrisys.dto.InventoryDTO;
import com.example.smartagrisys.entity.Inventory;
import com.example.smartagrisys.exception.BusinessException;
import com.example.smartagrisys.mapper.InventoryMapper;
import com.example.smartagrisys.service.InventoryService;
import com.example.smartagrisys.vo.InventoryVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 通用库存服务实现类
 */
@Slf4j
@Service
public class InventoryServiceImpl extends ServiceImpl<InventoryMapper, Inventory> implements InventoryService {

    @Override
    public List<InventoryVO> getInventoryByFarmerId(Long farmerId) {
        // 查询农户的所有库存
        LambdaQueryWrapper<Inventory> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Inventory::getFarmerId, farmerId)
               .orderByAsc(Inventory::getType)
               .orderByAsc(Inventory::getName);
        
        List<Inventory> inventoryList = this.list(wrapper);
        return convertToVOList(inventoryList);
    }

    @Override
    public List<InventoryVO> getInventoryByType(Long farmerId, String type) {
        // 查询农户的某类型库存
        List<Inventory> inventoryList = baseMapper.getInventoryByType(farmerId, type);
        return convertToVOList(inventoryList);
    }

    @Override
    public List<InventoryVO> getLowInventory(Long farmerId) {
        // 查询农户的低于预警阈值的库存
        List<Inventory> inventoryList = baseMapper.getLowInventory(farmerId);
        return convertToVOList(inventoryList);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long addInventory(Long farmerId, InventoryDTO dto) {
        Inventory inventory = new Inventory();
        BeanUtils.copyProperties(dto, inventory);
        inventory.setFarmerId(farmerId);
        
        // 保存库存
        this.save(inventory);
        log.info("农户 {} 添加库存: {}, 类型: {}", farmerId, inventory.getName(), inventory.getType());
        
        return inventory.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateInventory(Long farmerId, Long id, InventoryDTO dto) {
        // 查询库存是否存在
        Inventory inventory = getById(id);
        if (inventory == null) {
            throw new BusinessException(ResultCode.BAD_REQUEST, "库存记录不存在");
        }
        
        // 检查是否为此农户的库存
        if (!inventory.getFarmerId().equals(farmerId)) {
            throw new BusinessException(ResultCode.FORBIDDEN, "无权修改此库存记录");
        }
        
        // 更新库存
        BeanUtils.copyProperties(dto, inventory);
        inventory.setFarmerId(farmerId);
        
        log.info("农户 {} 更新库存: {}, 类型: {}", farmerId, inventory.getName(), inventory.getType());
        return this.updateById(inventory);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteInventory(Long farmerId, Long id) {
        // 查询库存是否存在
        Inventory inventory = getById(id);
        if (inventory == null) {
            throw new BusinessException(ResultCode.BAD_REQUEST, "库存记录不存在");
        }
        
        // 检查是否为此农户的库存
        if (!inventory.getFarmerId().equals(farmerId)) {
            throw new BusinessException(ResultCode.FORBIDDEN, "无权删除此库存记录");
        }
        
        log.info("农户 {} 删除库存: {}, 类型: {}", farmerId, inventory.getName(), inventory.getType());
        return this.removeById(id);
    }

    @Override
    public InventoryVO getInventoryById(Long id) {
        Inventory inventory = getById(id);
        if (inventory == null) {
            return null;
        }
        
        return convertToVO(inventory);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean checkAndUpdateInventory(Long farmerId, String type, Long itemId, String name, BigDecimal quantity) {
        log.info("开始检查并更新库存: 农户ID={}, 类型={}, 物品ID={}, 名称={}, 数量={}", farmerId, type, itemId, name, quantity);
        
        try {
            // 构建查询条件
            LambdaQueryWrapper<Inventory> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(Inventory::getFarmerId, farmerId)
                   .eq(Inventory::getType, type);
            
            // 按itemId或name查询
            if (itemId != null) {
                wrapper.eq(Inventory::getItemId, itemId);
                log.info("根据物品ID查询库存: {}", itemId);
            } else if (name != null && !name.isEmpty()) {
                wrapper.eq(Inventory::getName, name);
                log.info("根据物品名称查询库存: {}", name);
            } else {
                log.error("itemId和name均未提供");
                throw new BusinessException(ResultCode.BAD_REQUEST, "itemId和name至少需要提供一个");
            }
            
            // 查询库存
            Inventory inventory = this.getOne(wrapper);
            if (inventory == null) {
                log.error("未找到对应的库存记录: 农户ID={}, 类型={}, 物品ID={}", farmerId, type, itemId);
                throw new BusinessException(ResultCode.BAD_REQUEST, "找不到对应的库存记录");
            }
            
            log.info("找到库存记录: ID={}, 名称={}, 当前数量={}{}", 
                    inventory.getId(), inventory.getName(), inventory.getQuantity(), inventory.getUnit());
            
            // 检查库存是否足够
            if (inventory.getQuantity().compareTo(quantity) < 0) {
                log.error("库存不足: 当前库存={}{}, 需要={}{}", 
                         inventory.getQuantity(), inventory.getUnit(), quantity, inventory.getUnit());
                throw new BusinessException(ResultCode.BAD_REQUEST, "库存不足，当前库存:" + inventory.getQuantity() + 
                                          inventory.getUnit() + "，需要:" + quantity + inventory.getUnit());
            }
            
            // 计算剩余库存
            BigDecimal remainingQuantity = inventory.getQuantity().subtract(quantity);
            log.info("扣减后库存将变为: {}{}", remainingQuantity, inventory.getUnit());
            
            // 更新库存
            inventory.setQuantity(remainingQuantity);
            boolean result = this.updateById(inventory);
            
            if (result) {
                log.info("成功更新库存: 农户ID={}, 物品={}, 原库存={}{}, 扣减={}{}, 剩余={}{}",
                        farmerId, inventory.getName(), 
                        inventory.getQuantity().add(quantity), inventory.getUnit(),
                        quantity, inventory.getUnit(),
                        remainingQuantity, inventory.getUnit());
            } else {
                log.error("库存更新失败: 农户ID={}, 物品={}", farmerId, inventory.getName());
                throw new BusinessException(ResultCode.ERROR, "库存更新失败");
            }
            
            return result;
        } catch (BusinessException be) {
            // 业务异常直接抛出
            throw be;
        } catch (Exception e) {
            log.error("库存更新发生异常", e);
            throw new BusinessException(ResultCode.ERROR, "系统错误，库存更新失败");
        }
    }
    
    /**
     * 直接减少指定ID的库存数量
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean reduceInventoryDirectly(Long inventoryId, Long farmerId, BigDecimal quantity) {
        log.info("开始直接扣减库存: 库存ID={}, 农户ID={}, 数量={}", inventoryId, farmerId, quantity);
        
        try {
            // 查询库存
            Inventory inventory = this.getById(inventoryId);
            if (inventory == null) {
                log.error("库存记录不存在: ID={}", inventoryId);
                throw new BusinessException(ResultCode.BAD_REQUEST, "库存记录不存在");
            }
            
            // 验证是否属于当前农户
            if (!inventory.getFarmerId().equals(farmerId)) {
                log.error("无权操作此库存记录: 库存所属农户={}, 当前农户={}", inventory.getFarmerId(), farmerId);
                throw new BusinessException(ResultCode.FORBIDDEN, "无权操作此库存记录");
            }
            
            log.info("找到库存记录: ID={}, 名称={}, 当前数量={}{}", 
                    inventory.getId(), inventory.getName(), inventory.getQuantity(), inventory.getUnit());
            
            // 检查库存是否足够
            if (inventory.getQuantity().compareTo(quantity) < 0) {
                log.error("库存不足: 当前库存={}{}, 需要={}{}", 
                         inventory.getQuantity(), inventory.getUnit(), quantity, inventory.getUnit());
                throw new BusinessException(ResultCode.BAD_REQUEST, "库存不足，当前库存:" + inventory.getQuantity() + 
                                          inventory.getUnit() + "，需要:" + quantity + inventory.getUnit());
            }
            
            // 计算剩余库存
            BigDecimal remainingQuantity = inventory.getQuantity().subtract(quantity);
            log.info("扣减后库存将变为: {}{}", remainingQuantity, inventory.getUnit());
            
            // 更新库存
            inventory.setQuantity(remainingQuantity);
            boolean result = this.updateById(inventory);
            
            if (result) {
                log.info("成功更新库存: 库存ID={}, 物品={}, 原库存={}{}, 扣减={}{}, 剩余={}{}",
                        inventoryId, inventory.getName(), 
                        inventory.getQuantity().add(quantity), inventory.getUnit(),
                        quantity, inventory.getUnit(),
                        remainingQuantity, inventory.getUnit());
            } else {
                log.error("库存更新失败: 库存ID={}, 物品={}", inventoryId, inventory.getName());
                throw new BusinessException(ResultCode.ERROR, "库存更新失败");
            }
            
            return result;
        } catch (BusinessException be) {
            // 业务异常直接抛出
            throw be;
        } catch (Exception e) {
            log.error("库存更新发生异常", e);
            throw new BusinessException(ResultCode.ERROR, "系统错误，库存更新失败");
        }
    }
    
    /**
     * 将实体转换为VO
     */
    private InventoryVO convertToVO(Inventory inventory) {
        InventoryVO vo = new InventoryVO();
        BeanUtils.copyProperties(inventory, vo);
        
        // 计算总价值
        if (inventory.getQuantity() != null && inventory.getPrice() != null) {
            vo.setTotalValue(inventory.getQuantity().multiply(inventory.getPrice()).setScale(2, RoundingMode.HALF_UP));
        }
        
        return vo;
    }
    
    /**
     * 批量转换实体为VO
     */
    private List<InventoryVO> convertToVOList(List<Inventory> inventoryList) {
        if (inventoryList == null || inventoryList.isEmpty()) {
            return new ArrayList<>();
        }
        
        return inventoryList.stream()
                .map(this::convertToVO)
                .collect(Collectors.toList());
    }
} 
